<?php

namespace app\workers\service;

use app\common\formula\Calculate;
use app\model\MessageModel;
use app\model\RatingScaleFactorLevelModel;
use app\model\RatingScaleFactorModel;
use app\model\RatingScaleFactorWarningModel;
use app\model\RatingScaleModel;
use app\model\RatingScaleQuestionAnswerModel;
use app\model\WorkersTaskContinuousEvaluationModel;
use app\model\WorkersTaskFactorScoreContinuityModel;
use app\model\WorkersTaskFactorScoreModel;
use app\model\WorkersTaskModel;
use app\model\WorkersTaskRatingScaleModel;
use app\model\WorkersTaskUserModel;
use app\model\WorkersTaskUserResultContinuityModel;
use app\model\WorkersTaskUserResultModel;
use app\model\WorkersUserModel;
use think\facade\Queue;
use think\Service;

class RatingScaleService extends Service
{
    public string $message = '';
    public int $line;
    public array $resultData = [];
    public int $ResultId;
    public int $is_valid = 1;//是否有效【0否，1是】

    /**
     * 生成报告
     * @param array $data 用户提交的数据
     * @param int $channel 答题渠道【1.任务测评，2.自我测评】
     * @return bool
     */
    public function generateReport(array $data, int $channel): bool
    {
        try {
            $RatingScaleModel = new RatingScaleModel();
            $RatingScaleInfo = $RatingScaleModel->find($data['rating_scale_id']);
            //答题总分和因子总分
            $RatingScaleQuestionAnswerModel = new RatingScaleQuestionAnswerModel();
            $answerList = $RatingScaleQuestionAnswerModel->where('rating_scale_id', '=', $data['rating_scale_id'])->select()->toArray();
            $scoreData = [];
            foreach ($answerList as $item) {
                $scoreData[$item['id']] = $item;
            }
            $question_num = array_column($answerList, 'question_id');
            $question_num = count(array_unique($question_num));
            $scoreResults = [];
            $isWarning = 0;//是否预警
            $totalScore = 0;//总分
            if ($question_num > count($data['userAnswer'])) {
                $this->is_valid = 0;
            }
            foreach ($data['userAnswer'] as $AnswerId) {
                $questionNum = $scoreData[$AnswerId]['num'] ?? 0;
                if (!$questionNum) {
                    throw new \Exception('有题目未做，提交无效。请重新做题！');
                }
                $totalScore += $scoreData[$AnswerId]['score'] ?? 0;
                $scoreResults[$questionNum] = [
                    'user_answer_id' => $AnswerId,
                    'question_id' => $scoreData[$AnswerId]['question_id'] ?? 0,
                    'score' => $scoreData[$AnswerId]['score'] ?? 0,
                    'num' => $questionNum
                ];
            }
            $Calculate = new Calculate();
            $CalculateResults = $Calculate->getUserFactorScore($scoreResults, $data['rating_scale_id'], $RatingScaleInfo['mode_id'],$data['uid'],$this->is_valid);
            $factorResults = $CalculateResults['factorResults']??[];
            $this->is_valid = $CalculateResults['is_valid']??0;
            //生成报告
            $RatingScaleFactorLevelModel = new RatingScaleFactorLevelModel();
            $levelModels = $RatingScaleFactorLevelModel->where([
                'rating_scale_id' => $data['rating_scale_id'],
                'mode_id' => $RatingScaleInfo['mode_id']
            ])->with(['isTotal'])->select()->toArray();
            /**因子对应的等级预警分数,key为'因子id-预警等级'*/
            $factorWarningScores = [];
            /**预警array*/
            $warningArr = [];
            /**只显示最重要的一个等级*/
            $warningImportantArr = [];
            /**预警因子arr*/
            $warningFactorArr = [];
            foreach ($levelModels as $item) {
                $key = $item['factor_id'] . '-' . $item['level'];
                $factorWarningScores[$key] = ['low_range' => $item['low_range'], 'high_range' => $item['high_range'], 'is_total' => $item['is_total']];
            }
            $RatingScaleFactorWarningModel = new RatingScaleFactorWarningModel();
            $warningModels = $RatingScaleFactorWarningModel->where([
                'rating_scale_id' => $data['rating_scale_id'],
                'mode_id' => $RatingScaleInfo['mode_id']
            ])->select()->toArray();
            foreach ($warningModels as $arr) {
                //TODO::2类型暂时没数据不写
                //预警条件类型。1：单项，2：多项，3：总分关连预警
                switch ($arr['type']) {
                    case 1:
                    case 2:
                        if ($this->checkScoreIsInRange($arr, $factorWarningScores, $factorResults)) {
                            $warningArr[] = [
                                'name' => $arr['name'],
                                'important_level' => $arr['important_level'],
                                'is_total' => $factorWarningScores[$arr['factor_id'] . '-' . $arr['condition1_level']]['is_total']
                            ];
                            $isWarning = 1;
                            $warningFactorArr[] = $arr['factor_id'];
                            if (empty($warningImportantArr)) {
                                $warningImportantArr = [
                                    'name' => $arr['name'],
                                    'important_level' => $arr['important_level'],
                                    'id' => $arr['id'],
                                    'factor_id' => $arr['factor_id'],
                                ];
                            } else {
                                if ($arr['important_level'] > $warningImportantArr['important_level']) {
                                    $warningImportantArr = [
                                        'name' => $arr['name'],
                                        'important_level' => $arr['important_level'],
                                        'id' => $arr['id'],
                                        'factor_id' => $arr['factor_id'],
                                    ];
                                }
                            }
                        }
                        break;
                    case 3://涉及到顺序问题，总分关连预警放到循环外面处理
                        $totalWarningArr = ['name' => $arr['name'], 'total' => $arr['condition3_level_count']];
                        break;
                }
            }
            //总分关连预警
            $isTotalRelatedWarning = 0;
            if (!empty($warningArr) && !empty($totalWarningArr)) {
                $isTotalRelatedWarning = 1;
                $isWarning = 1;
                foreach ($warningArr as $value) {
                    //存在总分预警就不需要总分关连预警
                    if ($value['is_total'] == 1) {
                        $isTotalRelatedWarning = 0;
                        break;
                    }
                }
            }
            //因子预警情况end//
            //匹配因子所在的level数据
            foreach ($levelModels as $value) {
                if ($factorResults[$value['factor_id']]['score'] >= $value['low_range'] &&
                    $factorResults[$value['factor_id']]['score'] <= $value['high_range'] && $value['level'] !== 7
                ) {
                    //因子分数在范围内
                    if (!key_exists('overview', $factorResults[$value['factor_id']])) {
                        //条件2：针对总分异常，如果总分异常的数据库记录在总分等级前面，不加条件下面的elseif记录会被覆盖
                        $factorResults[$value['factor_id']]['overview'] = $value['overview'];
                        $factorResults[$value['factor_id']]['explain'] = $value['explain'];
                        $factorResults[$value['factor_id']]['factor_level_id'] = $value['id'];
                    }
                }
                if ($isTotalRelatedWarning == 1 && $value['level'] == 7) {//只有总分异常才会出现的level=7
                    $factorResults[$value['factor_id']]['overview'] = $value['overview'];
                    $factorResults[$value['factor_id']]['explain'] = $value['explain'];
                    $factorResults[$value['factor_id']]['factor_level_id'] = $value['id'];
                }
                //$value['level'] == 7 除总分外的异常因子≥1时.逻辑暂时写在外面【只要$this->isWarning == 1就显示$value['level'] == 7 的预警结果】
            }

            /*处理没有选答题的题目-开始*/
            $factorResults = array_values($factorResults);
            foreach ($factorResults as $k => $v) {
                if (!isset($v['overview'])) {
                    $factorResults[$k]['overview'] = '';
                }
                if (!isset($v['explain'])) {
                    $factorResults[$k]['explain'] = '';
                }
                if (!isset($v['factor_level_id'])) {
                    $factorResults[$k]['factor_level_id'] = 0;
                }
            }

            //因子
            $RatingScaleFactorModel = new RatingScaleFactorModel();
            $is_total = $RatingScaleFactorModel->where([
                ['rating_scale_id', '=', $data['rating_scale_id']],
                ['is_total', '=', 1],
                ['mode_id', '=', $RatingScaleInfo['mode_id']],
            ])->field('id,is_total')->find();
            //判断此量表是否有总分
            if (!empty($is_total) > 0) {
                $total = true;
            } else {
                $total = false;
            }
            $addFactorScores = [];
            foreach ($factorResults as $factorResult) {
                $addData = [
                    'factor_id' => $factorResult['factor_id'],
                    'factor_level_id' => $factorResult['factor_level_id'],
                    'score' => $factorResult['score'],
                    'time' => time()
                ];
                //因子是否预警
                if (in_array($factorResult['factor_id'], $warningFactorArr)) {
                    $addData['is_warning'] = 1;
                    $addData['warning_id'] = $warningImportantArr['id'] ?? 0;
                }
                $addFactorScores[] = $addData;
                //修改 普通报告与预警报告表的 测评总分字段（只有关联总分（预警等级==$@7）的才当做测评总分）
                if ($total && $factorResult['factor_id'] == $is_total['id']) {
                    //有总分，修改一下结果表的测评总分
                    $totalScore = $factorResult['score'];
                }
            }
            switch ($channel) {
                case 1:
                    $type = 'workers_task';
                    //任务测评
                    $ResultData = [
                        'unit_id' => $data['unit_id'],
                        'uid' => $data['uid'],
                        'task_id' => $data['task_id'],
                        'task_user_id' => $data['task_user_id'],
                        'rating_scale_id' => $data['rating_scale_id'],
//                        'result_read_auth' => $data['result_read_auth'],
//                        'answer_role' => $data['answer_role'],
                        'question_answer' => json_encode($data['userAnswer'], true),
                        'total_score' => $totalScore,
                        'finish_used_time' => $data['finish_used_time'],
                        'is_valid' => $this->is_valid,
                        'time' => time()
                    ];
                    //是否加入关注人群
//                    if ($isWarning == 1) {
//                        $ResultData['is_follow'] = 1;
//                    }
                    //是否预警
                    if ($isWarning == 1) {
                        $ResultData['is_warning'] = 1;
                        $ResultData['warning_id'] = $warningImportantArr['id'] ?? 0;
                        $ResultData['warning_factor_id'] = $warningImportantArr['factor_id'] ?? 0;
                    }
                    if (!$this->addTaskUserResult($ResultData, $addFactorScores)) throw new \Exception($this->message);
                    break;
                case 2:
                    $type = 'workers_task_continuity';
                    //预警连续测评
                    $ResultData = [
                        'unit_id' => $data['unit_id'],
                        'uid' => $data['uid'],
                        'task_id' => $data['task_id'],
                        'task_user_id' => $data['task_user_id'],
                        'rating_scale_id' => $data['rating_scale_id'],
//                        'answer_role' => $data['answer_role'],
                        'question_answer' => json_encode($data['userAnswer'], true),
                        'total_score' => $totalScore,
//                        'result_read_auth' => $data['result_read_auth'],
                        'finish_used_time' => $data['finish_used_time'],
                        'is_valid' => $this->is_valid,
                        'time' => time()
                    ];
                    //是否加入关注人群
//                    if ($isWarning == 1) {
//                        $ResultData['is_follow'] = 1;
//                    }
                    //是否预警
                    if ($isWarning == 1) {
                        $ResultData['is_warning'] = 1;
                        $ResultData['warning_id'] = $warningImportantArr['id'] ?? 0;
                    }
                    if (!$this->addTaskUserResultContinuity($ResultData, $addFactorScores)) throw new \Exception($this->message);
                    break;
                default:
                    // 如果没有匹配的值
                    throw new \Exception('参数错误！');
            }
            $RatingScaleInfo->inc('heat')->save();
            if (!Queue::push(\app\job\CronJob::class, [
                'method' => 'personCharts',
                'data' => [
                    'type' => $type,
                    'id' => $this->ResultId
                ],
            ], 'CronJob')) throw new \Exception('队列添加失败！');
            return true;
        } catch (\Exception $e) {
            $this->message = $e->getMessage();
            $this->line = $e->getLine();
            return false;
        }

    }

    /**
     * 任务用户答题结果（因子预警连续测评）
     * @param $ResultData
     * @param $addFactorScores
     * @return bool
     */
    public function addTaskUserResultContinuity($ResultData, $addFactorScores): bool
    {
        try {
            $TaskUserResultContinuityModel = new WorkersTaskUserResultContinuityModel();
            $TaskModel = new WorkersTaskModel();
            $TaskInfo = $TaskModel->find($ResultData['task_id']);
            $ResultData['result_read_auth'] = $TaskInfo['result_read_auth'];
            //添加结果记录
            $resultId = $TaskUserResultContinuityModel->insertGetId($ResultData);
            $this->ResultId = $resultId;
            foreach ($addFactorScores as &$item) {
                $item['result_id'] = $resultId;
            }
            //添加因子得分记录
            $TaskFactorScoreContinuityModel = new WorkersTaskFactorScoreContinuityModel();
            $TaskFactorScoreContinuityModel->saveAll($addFactorScores,false);
            return true;
        } catch (\Exception $e) {
            $this->message = $e->getMessage();
            $this->line = $e->getLine();
            return false;
        }

    }

    /**
     * 新增任务用户答题结果
     * @param $ResultData
     * @param $addFactorScores
     * @return bool
     */
    public function addTaskUserResult($ResultData, $addFactorScores): bool
    {
        try {
            $TaskUserResultModel = new WorkersTaskUserResultModel();
            $TaskUserModel = new WorkersTaskUserModel();
            $TaskModel = new WorkersTaskModel();
            $TaskInfo = $TaskModel->find($ResultData['task_id']);
            $ResultData['result_read_auth'] = $TaskInfo->result_read_auth;
            $is_has_after = $TaskInfo->is_has_after;
            //未完成数量
            $UnfinishedQuantity = $TaskUserModel->where([
                ['task_id', '=', $ResultData['task_id']],
                ['uid', '=', $ResultData['uid']],
                ['is_finish', '=', 0]
            ])->count();
            if ($UnfinishedQuantity <= 1) {
                //任务用户完成数加1
                $TaskInfo->user_complete_num++;
                $TaskInfo->user_complete_rate = number_format(($TaskInfo->user_complete_num/$TaskInfo->user_count)*100,2);
                $TaskInfo->inc('user_complete_num');
            }
            //更新任务量表统计
            $TaskRatingScaleModel = new WorkersTaskRatingScaleModel();
            $query = $TaskRatingScaleModel->where([
                'task_id' => $ResultData['task_id'],
                'rating_scale_id' => $ResultData['rating_scale_id']
            ])->inc('user_complete_num');
            if (isset($ResultData['is_warning']) && $ResultData['is_warning'] > 0) {
                $query->inc('warning_num');
                $warning_uid = $TaskUserResultModel->where([
                    ['task_id','=',$ResultData['task_id']],
                    ['is_warning','=',1]
                ])->column('uid');
                $warning_uid = array_unique($warning_uid);
                $warning_uid = array_diff($warning_uid,[$ResultData['uid']]);
                $warning_num = count($warning_uid) + 1;
                if ($warning_num > $TaskInfo->warning_num){
                    $TaskInfo->warning_num = $warning_num;
                }
            }
            $TaskInfo->save();
            $query->save();
            //添加结果记录
            $resultId = $TaskUserResultModel->insertGetId($ResultData);
            $this->ResultId = $resultId;
            //将任务设为完成
            $TaskUserModel->where('id', '=', $ResultData['task_user_id'])->update([
                'is_finish' => 1,
                'result_id' => $resultId
            ]);
            //因子得分
            foreach ($addFactorScores as &$item) {
                $item['result_id'] = $resultId;
                //开启预警连续测评
                if (isset($item['is_warning']) && $item['is_warning'] == 1 && $is_has_after == 1) {
                    $TaskContinuousEvaluationModel = new WorkersTaskContinuousEvaluationModel();
                    $continuity_rating_scale_id = $TaskContinuousEvaluationModel->where([
                        'task_id' => $ResultData['task_id'],
                        'rating_scale_id' => $ResultData['rating_scale_id'],
                        'factor_id' => $item['factor_id']
                    ])->value('continuity_rating_scale_id');
                    if ($continuity_rating_scale_id){
                        $this->resultData[] = $continuity_rating_scale_id;
                    }
                }
            }
            //添加因子得分记录
            $TaskFactorScoreModel = new WorkersTaskFactorScoreModel();
            $TaskFactorScoreModel->saveAll($addFactorScores,false);
            //系统消息
            $WorkersUserModel = new WorkersUserModel();
            $user_name = $WorkersUserModel->where('id','=',$ResultData['uid'])->value('name');
            $MessageData = [];
            if (isset($ResultData['is_warning']) && $ResultData['is_warning'] > 0) {
                $MessageData[] = [
                    'uid' => $TaskInfo['uid'],
                    'type' => 11,
                    'title' => '教职工测评',
                    'content' => '教职工'.$user_name.'发现预警，测评任务'.$TaskInfo['name'].'，请及时处理。',
                    'time' => time()
                ];
            }
            $MessageData[] = [
                'uid' => $TaskInfo['uid'],
                'type' => 10,
                'title' => '教职工测评',
                'content' => '教职工'.$user_name.'完成了'.$TaskInfo['name'].'测评任务，已生成测评报告，请及时查看。',
                'time' => time()
            ];
            $MessageModel = new MessageModel();
            $MessageModel->insertAll($MessageData);
            return true;
        } catch (\Exception $e) {
            $this->message = $e->getMessage();
            $this->line = $e->getLine();
            return false;
        }

    }

    /**
     * 检查分数在范围内
     * @param $warningArr
     * @param $factorWarningScores
     * @param $factorResults
     * @return bool
     */
    private function checkScoreIsInRange($warningArr, $factorWarningScores, $factorResults): bool
    {
        return ($factorResults[$warningArr['factor_id']]['score'] >= $factorWarningScores[$warningArr['factor_id'] . '-' . $warningArr['condition1_level']]['low_range']
            &&
            $factorResults[$warningArr['factor_id']]['score'] <= $factorWarningScores[$warningArr['factor_id'] . '-' . $warningArr['condition1_level']]['high_range']);
    }

}